#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <assert.h>
using namespace std;
//继承是面向对象复用的重要手段
#if 0
class People
{
public:
    void identity()
    {
        cout << "身份验证成功" << endl;
    }
private:
    string name;
    size_t age;
    string phone;
};
class Teacher : public People
{
public:
    void teaching()
    {
        cout << "授课中" << endl;
    }
private:
    string WorkNumber;
};
class Student :public People
{
public:
    void study()
    {
        cout << "学习中" << endl;
    }
private:
    string StudentId;
};
#endif

#if 0
class Person
{
public://公有
    void Print()
    {
        cout << _name << endl;
    }
protected://保护
    string _name = "张三";
private:
    int _age;
};
class Student : public Person
{
public:
    void Func()
    {
        cout << _name << endl;
    }
protected:
    int _stunum;//学号
};
#endif

#if 0
//继承的方式实现栈
namespace hao
{
    template<class T>
    class stcak : public vector<T>
    {
    public:
        void push(const T& val)
        {
            vector<T>::push_back(val);
        }
        void pop()
        {
            vector<T>::pop_back();
        }
        bool empty()
        {
            return vector<T>::empty();
        }
        T& top()
        {
            return vector<T>::back();
        }
        size_t size()
        {
            return vector<T>::size();
        }
    private:
    };
}
void stack_test()
{
    hao::stcak<int> s;
    s.push(1);
    s.push(2);
    s.push(3);
    s.push(4);
    s.push(5);
    while(!s.empty())
    {
        cout << s.top() << endl;
        s.pop();
    }
}
#endif


#if 0
//写一个通用的容器打印函数
template<class Container>
void Print(const Container& c)
{
    //Container::const_iterator it = c.begin(); err
    //typename Container::const_iterator it = c.begin();
    auto it = c.begin();
    while(it != c.end())
    {
        cout << *it << " ";
        it++;
    }
    cout << endl;
}

void Print_test()
{
    vector<int> v({1,2,3,4,5,6,7,8,9,10});
    list<int> l({1,2,3,4,5,6,7,8,9,10});
    string s = "hello world";
    Print(v);
    Print(l);
    Print(s);
}
#endif
#if 0
class Person
{
protected://保护
    string _name = "张三";
public:
    int _age = 18;
};
class Student : public Person
{
protected:
    int _stunum;//学号
public:
    int _age = 4;
};
int main()
{
    Student s;
    // Person* pp = &s;
    // Person& pr = s;
    // cout << s._age << endl;
    // pr._age++;
    // cout << s._age << endl;
    // pp->_age = 100;
    // cout << s._age << endl;
    cout << s.Person::_age << endl;
    cout << s._age << endl;
    return 0;
}
#endif

/********************************************vs 2019*****************************************************/

#define _CRT_SECURE_NO_WARNINGS 1

#if 0
class Person
{
public:
	void identity()
	{
		cout << "身份验证成功" << endl;
	}
protected:
	string _name = "张三";
	string _address;
	string _tel;
	int _age = 18;
};
class Student : public Person
{
public:
	void study()
	{
		cout << "学习" << endl;
	}
protected:
	int _stuid;// 学号
};

class Teacher : public Person//继承
{
public:
	void teaching()
	{
		cout << "授课" << endl;
	}
protected:
	string title;// 职称
};
void test()
{
	Student s;
	Teacher t;
	s.identity();
	s.study();
	t.identity();
	t.teaching();
}
#endif

#if 0
//struct默认是公有继承,class默认是私有继承
class Person
{
public:
	void P()
	{
		cout << "Person" << endl;
	}
};
class Student :public Person
{
public:
	void S()
	{
		cout << "Student" << endl;
	}
};
void test1()
{
	Student s;
	s.S();
	s.P();
}
#endif
//继承类模板
//栈
#if 0
namespace Aurora
{
	template<typename T>
	class stack : public std::vector<T>
	{
	public:
		void push(const T& val)
		{
			std::vector<T>::push_back(val);
		}
		void pop()
		{
			std::vector<T>::pop_back();
		}
		bool empty()
		{
			return std::vector<T>::empty();
		}
		const T& top() const
		{
			return std::vector<T>::back();
		}
		const size_t size() const
		{
			return std::vector<T>::size();
		}
	};
}
void StackTest()
{
	Aurora::stack<int> s;
	s.push(1);
	s.push(2);
	s.push(3);
	s.push(4);
	while (!s.empty())
	{
		std::cout << s.top() << " ";
		s.pop();
	}
	std::cout << std::endl;
}
#endif
//实现一个打印任何容器的打印函数
#if 0
namespace Aurora
{
	template<class Container>
	void Print(const Container& c)
	{
		//typename Container::const_iterator it = c.begin();
		auto it = c.begin();
		while (it != c.end())
		{
			std::cout << *it << " ";
			it++;
		}
		std::cout << std::endl;
	}
}
void PrintTest()
{
	std::string s = "hello world";
	std::vector<int> v = { 1,2,3,4,5,6,7,8,9,10 };
	std::list<int> l({ 1,2,3,4,5,6,7,8,9,10 });
	Aurora::Print(s);
	Aurora::Print(v);
	Aurora::Print(l);
}
#endif
//基类和派生类的转换
#if 0
namespace Aurora
{
	//基类
	class Person
	{
	protected:
		std::string _name;
		std::string _sex;
	public:
		size_t age = 18;
	};
	//派生类
	class Student : public Person
	{
	public:
		size_t _No;
	};
}
void test2()
{
	Aurora::Student s;
	//会产生切片/切割
	Aurora::Person* pp = &s;
	Aurora::Person& pr = s;
	//赋值
	Aurora::Person ps = s;
	std::cout << s.age << std::endl;
	pp->age++;
	std::cout << s.age << std::endl;
	pr.age = 100;
	std::cout << s.age << std::endl;
	s.age = 200;
	std::cout << s.age << std::endl;
}
#endif
#if 0
namespace Aurora
{
	class Person
	{
	public:
		/*void Func()
		{
			std::cout << "Person" << std::endl;
		}*/
	protected:
		std::string _name = "张三";
		size_t _num = 111;
	};
	class Student : public Person
	{
	public:
		/*void Func()
		{
			std::cout << "Student" << std::endl;
		}*/
		void Print()
		{
			std::cout << "姓名:" << _name << std::endl;
			std::cout << "身份证号码:" << Person::_num << std::endl;
			std::cout << "学号:" << _num << std::endl;
		}
	protected:
		size_t _num = 123;//学号
	};
}
void FuncTest()
{
	/*Aurora::Student s;
	s.Func();
	s.Aurora::Person::Func();*/
	Aurora::Student s;
	s.Print();
}
#endif
#if 0
namespace Aurora
{
	class A
	{
	public:
		int Age() { return _age; }
		int Tel() { return _tel; }
	private:
		int _age = 18;
		int _tel = 112;
	};
}
void test03()
{
	Aurora::A a;
	Aurora::A b(a);
	Aurora::A c;
	c = a;
	cout << a.Age() << endl;
	cout << a.Tel() << endl;
	cout << b.Age() << endl;
	cout << b.Tel() << endl;
	cout << c.Age() << endl;
	cout << c.Tel() << endl;
}
#endif

//派生类的默认成员函数
#if 0
class Person
{
public:
	//Person(const char* name)
	Person(const char* name)
		: _name(name)
	{
		cout << "Person()" << endl;
	}

	Person(const Person& p)
		: _name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}

	Person& operator=(const Person& p)
	{
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p)
			_name = p._name;

		return *this;
	}

	~Person()
	{
		cout << "~Person()" << endl;
	}
protected:
	string _name; // 姓名
};

class Student : public Person
{
public:
	Student(const char* name,int num,const char* address)
		:Person(name)
		,_num(num)
		,_address(address)
	{
		cout << "Student()" << endl;
	}
	Student(const Student& s)
		:Person(s)//切割/切片
		,_num(s._num)
		,_address(s._address)
	{
		cout << "Student(const Student& s)" << endl;
	}
	Student& operator=(const Student& s)
	{
		cout << "Student& operator=(const Student& s)" << endl;
		if (this != &s)
		{
			_address = s._address;
			_num = s._num;
			Person::operator=(s);//切片/切割,子类/父类operator=构成隐藏,得指定类域
		}
		return *this;
	}
	~Student()
	{
		//不需要写,子类析构函数结束后,会自动调用父类析构
		//Person::~Person();
		cout << "~Student()" << endl;
		//detete[] _ptr;
	}
protected:
	int _num; //学号
	string _address;

	//int* _ptr = new int[10];
};
//要点:
//不写,编译器默认生成的行为是什么?
//默认生成不符合我们需求,自己写,得怎么写?
// 
//特点:子类中继承下来的父类成员当做一个整体对象
//
//构造
//默认:子类成员 内置类型(有缺省值就有,没有不确定)和自定义类型(默认构造) + 父类成员(必须调用父类默认构造)

//拷贝构造:子类成员 内置类型(值拷贝)和自定义类型(这个类型的拷贝构造) + 父类(必须调用父类拷贝构造)

//赋值重载:类似拷贝构造

//析构:内置类型(不处理)和自定义类型(调用它的析构) + 父类(调用它的析构)
//自己实现的话,注意不需要显示调用父类析构,子类析构函数结束后,会自动调用父类析构
void Test()
{
	Student s1("张三", 18, "西安");
	Student s2(s1);
	Student s3("李四", 19, "上海");
	s1 = s3;
}
#endif

//不能被继承的类
#if 0
class Base //final
{
public:
	void func()
	{
		cout << "base::func" << endl;
	}
protected:
	int a = 1;
private:
	//C++98的方法 - 把构造函数私有化
	//构造函数私有化就意味着
	//派生类构造是必须去调用父类的构造的,但父类的构造是私有的,私有的在
	//派生类是不可见的,所以间接的就限制了这个派生类就生成不了对应的对象
	//因为生成对象就得调用构造,无论是自己显示写还是自动生成都搞不定,因为
	//调不到父类的,父类是不可访问的,这是一个间接的方法

	//Base(){}

	//C++11方法 - 增加关键字final
	//final修饰这个类之后就说明这个类是最终类,在语法上给硬控了,
};
class Derive :public Base
{
	void func4() { cout << "Derive::func4" << endl; }
protected:
	int b = 2;
};
void final_test()
{
	Base b;
	Derive d;
}
#endif

#if 0
//继承与友元
class Student;//声明
class Person
{
public:
	friend void Display(const Person& p, const Student& s);
protected:
	string _name;//姓名
};
class Student : public Person
{
public:
	friend void Display(const Person& p, const Student& s);
protected:
	int _stuNum;//学号
};
void Display(const Person& p, const Student& s)
{
	cout << p._name << endl;
	cout << s._stuNum << endl;
}
void test05()
{
	Person p;
	Student s;
	Display(p, s);
}
#endif

#if 0
//继承与静态成员
class Person
{
public:
	string _name;
	static int _count;
};
int Person::_count = 0;
class Student : public Person
{
protected:
	int _stuNum;
};
//静态成员变量在继承体系中只有一份
void test06()
{
	Person p;
	Student s;
	cout << &p._name << endl;
	cout << &s._name << endl;
	cout << &s._count << endl;
	cout << &p._count << endl;
	cout << &Person::_count << endl;
	cout << &Student::_count << endl;
}
#endif
//多继承
class Person
{
public:
	string _name;
};
class Student : virtual public Person
{
protected:
	int _num;
};
class Teacher : virtual public Person
{
protected:
	int _id;
};
class Assistant : public Student, public Teacher
{
protected:
	string _majorCourse;
};
int main()
{
	Assistant a;
	a.Student::_name = "xxx";
	a.Teacher::_name = "yyy";
	a._name = "aaa";
	return 0;
}


/*
2025.1.16 假期补课打卡第七天 继承
继承是面向对象的三大特性之一,继承机制是面向对象
程序设计使代码可以复用的最重要的手段,它允许我们
在保持原有类特性的基础上进行扩展,增加方法和属性,
这样产生新的类,称派生类,继承呈现了面向对象程序
设计的层次结构,体现了由简单到复杂的认知过程,以
前我们接触的函数层次的复用,继承是类设计层次的复
用,面向对象的三大特性也是面试或笔试中常考的。
笔记:https://blog.csdn.net/m0_74271757/article/details/143361840?spm=1001.2014.3001.5501
*/